package com.socket.io.server;

import com.alibaba.fastjson.JSON;
import com.socket.io.msg.Msg;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @auther zhangwj
 * @date 2020/9/23 2:14 下午
 */
public class IOServer {
    static Map<Integer, Socket> socketMap = new HashMap<>();

    public static void main(String[] args) {
        new Thread(new CheckMap()).start();
        Server.start(8080);
    }
}


class Server {
    public static void start(int port) {

        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            // 阻塞
            Socket socket;
            while ((socket = serverSocket.accept()) != null) {
                new Thread(new Handle(socket)).start();
            }
        } catch (IOException e) {
            System.out.println("Socket异常");
        } finally {
            if (null != serverSocket) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    System.out.println("关闭ServerSocket异常");
                }
            }
        }
    }
}

class Handle implements Runnable {

    private Socket socket;

    Handle(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream inputStream = null;
        try {
            inputStream = this.socket.getInputStream();
            if (null != inputStream) {
                byte[] bytes = new byte[1024];
                int len;
                StringBuilder sb = new StringBuilder();
                while ((len = inputStream.read(bytes)) > 0) {
                    //注意指定编码格式，发送方和接收方一定要统一，建议使用UTF-8
                    sb.append(new String(bytes, 0, len, StandardCharsets.UTF_8));
                    if (sb.toString().indexOf("}") > 0) {
                        break;
                    }
                }
                if (socket.isClosed()) {
                    System.out.println("已关闭1111");
                }
                String msgStr = sb.toString();
                if (StringUtils.isEmpty(msgStr)) {
                    System.out.println("数据为空");
                    this.socket.close();
                }
                Msg msg = JSON.parseObject(sb.toString(), Msg.class);
                if (null == msg) {
                    System.out.println("Msg数据为空");
                    this.socket.close();
                    return;
                }
                System.out.println("msg=" + msg.toString());
                if (null == msg.getClientId()) {
                    System.out.println("clientId数据为空");
                    this.socket.close();
                    return;
                }
                IOServer.socketMap.put(msg.getClientId(), this.socket);
                System.out.println("添加成功" + IOServer.socketMap.size());
                if (null != msg.getSendClientId()) {
                    Socket socket = IOServer.socketMap.get(msg.getSendClientId());
                    if (null != socket) {
                        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                        out.println("我是" + msg.getClientId() + "给你发送了一条消息:" + msg.getMsg());
                        out.close();
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("读异常");
        }

    }
}

class CheckMap implements Runnable {

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (IOServer.socketMap.size() > 0) {
                Iterator<Map.Entry<Integer, Socket>> iterator = IOServer.socketMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<Integer, Socket> entry = iterator.next();
                    Socket socket = entry.getValue();
                    if (null != socket) {
                        if (socket.isClosed()) {
                            System.out.println("已关闭");
                            iterator.remove();
                        }
                    }
                }
            }
        }
    }
}